package com.alex.maze.level;

import com.alex.maze.level.block.SolidBlock;
import com.alex.maze.level.block.Block;
import com.alex.maze.Art;
import com.alex.maze.entities.Entity;
import com.alex.maze.entities.PushingEntity;
import com.alex.maze.graphics.Sprite;
import com.alex.maze.level.block.InvisBlock;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;

public class Level
{
    public Block[] blocks;
    
    public int LSIRINA;
    public int LVISINA;
    
    private Block cvrstZid = new SolidBlock();
    
    public static int xSpawn;
    public static int ySpawn;
    
    public List<Entity> entities = new ArrayList<Entity>();
    
    public void init(String name, int sirina, int visina, int[] pixels)
    {
        int bojaZida = Art.getCol(0xB3CEE2); // 0xB3CEE2 - Neutralne boje 0x648CAD - old
        int bojaPoda = Art.getCol(0x9CA09B); // 0x9CA09B - Neutralne boje 0xD89C63 - old
        int bojaPlafona = Art.getCol(0x9CA09B); //0x9CA09B - Neutralne boje 0xD89C63 - old
        
        cvrstZid.boja = bojaZida;
        
        LSIRINA = sirina;
        LVISINA = visina;
        
        blocks = new Block[sirina * visina];
        
        for (int y = 0; y < visina; y++)
        {
            for (int x = 0; x < sirina; x++)
            {
                int col = pixels[x + y * sirina] & 0xFFFFFF;
                Block block = getBlock(x, y, col);
                
                block.boja = bojaZida;
                block.bojaPoda = bojaPoda;
                block.bojaPlafona = bojaPlafona;
                 
                blocks[x + y * sirina] = block;
                
                decorateBlock(x, y, block, col);
            }
        }
    }
    
    public void addEntity(Entity e)
    {
        entities.add(e);
        e.nivo = this;
        e.azurirajPoziciju();
    }
        
    protected void decorateBlock(int x, int y, Block block, int col)
    {
         if (col == 0xFFFF00)
         {
             xSpawn = x;
             ySpawn = y;
         }
         if (col == 0x4C4C4C)
         {
             block.addSprite(new Sprite(0, 0, 0, 1, 0x202020));
             block.blockMotion = true;
         }
         if (col == 0x00ff00) // travica
         {
             block.addSprite(new Sprite(0, 0, 0, 0, 0x90F090));
         }
         if (col == 0xAA5500)
         {
             addEntity(new PushingEntity(x, y));
         }
    }
    
    protected Block getBlock(int x, int y, int col)
    {
        if (col == 0xFFFFFF)
        {
            return new SolidBlock();
        }
        if (col == 0x00FFFF)
        {
            return new InvisBlock();
        }
        
        return new Block();
    }

    
    public Block getBlock(int x, int y)
    {
        if (x < 0 || y < 0 || x >= LSIRINA || y >= LVISINA)
        {
            return cvrstZid;
        }
        return blocks[x + y * LSIRINA];
    }
    
    private static Map<String, Level> loaded = new HashMap<String, Level>();
    
    public static Level loadLevel(String name)
    {
        if (loaded.containsKey(name))
        {
            loaded.get(name);
        }
        try
        {
            BufferedImage slika = ImageIO.read(Level.class.getResource("/levels/" + name + ".png"));
            
            int[] pikseli = new int[slika.getWidth() * slika.getHeight()];
            slika.getRGB(0, 0, slika.getWidth(), slika.getHeight(), pikseli, 0, slika.getWidth()); 
            
            Level level = Level.byName(name);
            level.init(name, slika.getWidth(), slika.getHeight(), pikseli);
            loaded.put(name, level);
            
            return level;
        }
        catch (IOException e)
        {
            /* Ako fajla(slike) nema onda nemoj da pokrenes program i baci RuntimeException */
            throw new RuntimeException(e);
        }
    }
    
    private static Level byName(String name)
    {
        try
        {
            name = name.substring(0,1).toUpperCase() + name.substring(1);
            return (Level) Class.forName("com.alex.maze.level." + name + "Level").newInstance();
        } catch (Exception e)
        {
            throw  new RuntimeException(e);
        }
    }
    
    public void update()
    {
        for (int i = 0; i < entities.size(); i++)
        {
            Entity e = entities.get(i);
            e.azuriraj();
            e.azurirajPoziciju();
            if (e.isRemoved())
            {
                entities.remove(i--);
            }
        }
        for (int y = 0; y < LVISINA; y++)
        {
            for (int x = 0; x < LSIRINA; x++)
            {
                // Ovo radi okej imam tacno tri objekta!
                //int brojac = blocks[x + y * LSIRINA].entities.size();
                //if (brojac > 0)
                //{
                //    System.err.println(brojac);
                //}
                blocks[x + y * LSIRINA].update();
            }
        }
    }
}
